package com.shortlink.openserver.util;

import cn.hutool.core.util.ObjectUtil;
import com.shortlink.common.exception.ServiceException;
import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import javax.crypto.SecretKey;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * JWT工具类
 *
 * @author wp
 */
@Component
@Setter
@Getter
@ConfigurationProperties(value = "shortlink-open-server.token")
public class JwtUtils {
    private static final String UV_ID = "uvId";
    /**
     * 密钥
     */
    private String secret;
    /**
     * 有效期
     */
    private long jwtExpiration;

    /**
     * 生成JWT令牌
     */
    public String generateToken(String uvId) {
        Date now = new Date();
        Date expiryDate = new Date(now.getTime() + jwtExpiration);

        Map<String, Object> map = new HashMap<>();
        map.put(UV_ID, uvId);
        SecretKey key = Keys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8));
        return Jwts.builder()
                .subject(uvId)
                .claims(map)
                .issuedAt(now)
                .expiration(expiryDate)
                .signWith(key)
                .compact();
    }

    /**
     * 解析JWT令牌
     */
    public String parseToken(String token) {
        if (ObjectUtil.isEmpty(token)) {
            return null;
        }
        SecretKey key = Keys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8));
        Claims claims;
        try {
            claims = Jwts.parser()
                    .verifyWith(key)
                    .build()
                    .parseSignedClaims(token)
                    .getPayload();
        } catch (JwtException e) {
            return null;
        } catch (IllegalArgumentException e) {
            throw new ServiceException("JWT解析错误");
        }
        return claims.get(UV_ID, String.class);
    }
}